package controller.backstage;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.time.format.DateTimeFormatter;
import	java.util.Arrays;

import com.alibaba.druid.util.StringUtils;
import com.google.gson.*;
import model.Query;
import model.Result;
import model.bo.GoodsBO;
import model.bo.ReplyBO;
import model.bo.SpecBO;

import model.InnerResult;
import service.GoodsService;
import service.impl.GoodsServiceImpl;
import utils.FileUploadUtils;
import utils.HttpUtils;
import utils.ModelUtils;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.function.Function;

import static model.InnerResult.Status.FULFILLED;

@WebServlet("/api/admin/goods/*")
public class GoodsServlet extends HttpServlet {
    private GoodsService goodsService = new GoodsServiceImpl();
    private final String URI_PREFIX = "/api/admin/goods/";
    private final Gson GSON = new GsonBuilder()
            .registerTypeAdapter(Timestamp.class, new TimestampSerializer())
            .create();

    private static class TimestampSerializer implements JsonSerializer<Timestamp> {
        final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
        @Override
        public JsonElement serialize(Timestamp timestamp, Type type, JsonSerializationContext jsonSerializationContext) {
            return new JsonPrimitive(timestamp.toLocalDateTime().format(dtf));
        }
    }

    private final Function<InnerResult, Result> FILLER = dto -> {
        if (dto.getStatus() == FULFILLED) {
            return Result.fulfill(dto.getObject());
        } else {
            return Result.reject(dto.getObject().toString());
        }
    };


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        String action = req.getRequestURI().replace(URI_PREFIX, "");
        try {
            switch (action) {
                case "getType":
                    getType(req, resp);
                    break;
                case "getGoodsByType":
                    getGoodsByType(req, resp);
                    break;
                case "getGoodsInfo":
                    getGoodsInfo(req, resp);
                    break; //id=?
                case "deleteGoods":
                    deleteGoods(req, resp);
                    break;
                case "noReplyMsg":
                    noReplyMsg(req, resp);
                    break;
                case "repliedMsg":
                    repliedMsg(req, resp);
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void repliedMsg(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        InnerResult dto = goodsService.repliedMsg();
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    private void noReplyMsg(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        InnerResult dto = goodsService.noReplyMsg();
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    private void deleteGoods(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String id = req.getParameter("id");
        if (!StringUtils.isNumber(id) || Integer.parseInt(id) < 1) {
            resp.getWriter().print(GSON.toJson(Result.reject("非法参数")));
            return;
        }
        InnerResult dto = goodsService.deleteGoods(id, getServletContext().getRealPath("/"));
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    private void getGoodsInfo(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String id = req.getParameter("id");
        if (!StringUtils.isNumber(id) || Integer.parseInt(id) < 1) {
            resp.getWriter().print(GSON.toJson(Result.reject("非法参数")));
            return;
        }
        InnerResult dto = goodsService.getGoodsInfo(id);
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    private void getGoodsByType(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Query query = HttpUtils.getQuery(req);
        if (ModelUtils.isInvalid(query)) {
            resp.getWriter().print(GSON.toJson(Result.reject("非法参数")));
            return;
        }
        InnerResult dto = goodsService.getGoodsByType(query);
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    private void getType(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        InnerResult dto = goodsService.getTypes();
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String action = req.getRequestURI().replace(URI_PREFIX, "");
        switch (action) {
            case "imgUpload": imgUpload(req, resp); break;
            case "addGoods": addGoods(req, resp); break; //name, typeId, img, desc, specList(specName, stockNUm, unitPrice)
            case "addSpec": addSpec(req, resp); break; //goodsId, specName, stockNUm, unitPrice
            case "deleteSpec": deleteSpec(req, resp); break; //goodsId, specName
            case "updateGoods": updateGoods(req, resp); break; //id, name, typeId, img, desc, specList
            case "reply": reply(req, resp); break;
        }
    }

    private void reply(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String requestBody = HttpUtils.getRequestBody(req);
        ReplyBO reply;
        try {
            reply = GSON.fromJson(requestBody, ReplyBO.class);
        } catch (JsonParseException e) {
            resp.getWriter().print(GSON.toJson(Result.reject("非法参数")));
            return;
        }
        if (ModelUtils.isInvalid(reply, Collections.singletonList("content"))) {
            resp.getWriter().print(GSON.toJson(Result.reject("信息不能为空")));
            return;
        }
        InnerResult dto = goodsService.reply(reply);
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    private void deleteSpec(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String requestBody = HttpUtils.getRequestBody(req);
        SpecBO spec = GSON.fromJson(requestBody, SpecBO.class);
        if (ModelUtils.isInvalid(spec, Arrays.asList("goodsId", "specName"))) {
            resp.getWriter().print(GSON.toJson(Result.reject("信息不能为空")));
            return;
        }
        InnerResult dto = goodsService.deleteSpec(spec);
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    private void addSpec(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String requestBody = HttpUtils.getRequestBody(req);
        SpecBO spec;
        try {
            spec = GSON.fromJson(requestBody, SpecBO.class);
        } catch (JsonSyntaxException e) { //empty string，可能gson在转换的时候如果bean中是数字类型的，遇到空串就抛exception，要改很多
            resp.getWriter().print(GSON.toJson(Result.reject("错误的输入")));
            return;
        }
        if (ModelUtils.isInvalid(spec, Arrays.asList("goodsId", "specName", "stockNum", "unitPrice"))) {
            resp.getWriter().print(GSON.toJson(Result.reject("信息不能为空")));
            return;
        }
        InnerResult dto = goodsService.addSpec(spec);
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    private void updateGoods(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String requestBody = HttpUtils.getRequestBody(req);
        GoodsBO goodsBO = GSON.fromJson(requestBody, GoodsBO.class);
        InnerResult dto = goodsService.updateGoods(goodsBO, getServletContext().getRealPath("/"));
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    private void addGoods(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        String requestBody = HttpUtils.getRequestBody(req);
        GoodsBO goodsBO;
        try {
            goodsBO = GSON.fromJson(requestBody, GoodsBO.class);
        } catch (JsonSyntaxException e) { //empty string，可能gson在转换的时候如果bean中是数字类型的，遇到空串就抛exception，要改很多
            resp.getWriter().print(GSON.toJson(Result.reject("错误的输入")));
            return;
        }
        InnerResult dto = goodsService.addGoods(goodsBO);
        resp.getWriter().print(GSON.toJson(FILLER.apply(dto)));
    }

    private void imgUpload(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Map<String, Object> map = FileUploadUtils.parse(req);
        if (null == map) {
            return;
        }
        String path = (String)map.get("file");

        //前端服务器应该知道去哪里获取资源，这里的路径不加域名端口号
        //且这里返回的图片路径是要写入数据库的，更不应加域名端口号
        resp.getWriter().print(GSON.toJson(Result.fulfill(path)));
    }
}
